洛谷试炼场 4-17 树链剖分 Diposting di 2019-04-24 | Edited on 2019-02-09 [ZJOI2008]树的统计 (入门题,链最大值,链和)思路123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll mod=998244353;const int maxn=1e6+50;const ll inf=0x3f3f3f3f3f3f3f3fLL;int n,q,a[maxn];vector<int>G[maxn];int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];int id[maxn],pre[maxn],cnt=0;void dfs1(int u,int f,int deep){ size[u]=1; fa[u]=f;son[u]=0;dep[u]=deep; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==f)continue; dfs1(v,u,deep+1); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; }}void dfs2(int u,int root){ id[u]=++cnt;top[u]=root;pre[cnt]=u; if(son[u])dfs2(son[u],root); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); }}int sumv[maxn<<2],maxv[maxn<<2];inline void pushup(int o){ sumv[o]=sumv[o<<1]+sumv[o<<1|1]; maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);}void build(int o,int l,int r){ int mid=(l+r)/2; if(l==r){ sumv[o]=maxv[o]=a[pre[l]];return; } build(o<<1,l,mid);build(o<<1|1,mid+1,r); pushup(o);}void update(int o,int l,int r,int q,int v){ int mid=(l+r)/2; if(l==r){ sumv[o]=maxv[o]=v;return; } if(q<=mid)update(o<<1,l,mid,q,v); else update(o<<1|1,mid+1,r,q,v); pushup(o);}int querysum(int o,int l,int r,int ql,int qr){ int mid=(l+r)/2,ans=0; if(ql<=l&&r<=qr)return sumv[o]; if(ql<=mid)ans+=querysum(o<<1,l,mid,ql,qr); if(qr>mid)ans+=querysum(o<<1|1,mid+1,r,ql,qr); return ans;}int querymax(int o,int l,int r,int ql,int qr){ int mid=(l+r)/2,ans=-inf; if(ql<=l&&r<=qr)return maxv[o]; if(ql<=mid)ans=max(ans,querymax(o<<1,l,mid,ql,qr)); if(qr>mid)ans=max(ans,querymax(o<<1|1,mid+1,r,ql,qr)); return ans;}int qsum(int u,int v){ int ans=0; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ans+=querysum(1,1,n,id[top[u]],id[u]); u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v); ans+=querysum(1,1,n,id[v],id[u]); return ans;}int qmax(int u,int v){ int ans=-inf; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ans=max(ans,querymax(1,1,n,id[top[u]],id[u])); u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v); ans=max(ans,querymax(1,1,n,id[v],id[u])); return ans;}int main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); cin>>n; for(int i=1;i<n;i++){ int u,v; cin>>u>>v;G[u].push_back(v);G[v].push_back(u); } for(int i=1;i<=n;i++)cin>>a[i]; fa[1]=1;dfs1(1,0,1);dfs2(1,1);build(1,1,n); int q; cin>>q; while(q--){ int x,y;char s[100]; cin>>s>>x>>y; if(s[1]=='H')update(1,1,n,id[x],y); else if(s[1]=='M')cout<<qmax(x,y)<<endl; else if(s[1]=='S')cout<<qsum(x,y)<<endl; } return 0;} P2486 [SDOI2011]染色 (区间操作很难 未AC)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll mod=998244353;const int maxn=1e6+50;const ll inf=0x3f3f3f3f3f3f3f3fLL;int n,q,col[maxn];vector<int>G[maxn];int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];int id[maxn],pre[maxn],cnt=0;void dfs1(int u,int f,int deep){ size[u]=1; fa[u]=f;son[u]=0;dep[u]=deep; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==f)continue; dfs1(v,u,deep+1); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; }}void dfs2(int u,int root){ id[u]=++cnt;top[u]=root;pre[cnt]=u; if(son[u])dfs2(son[u],root); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); }}struct node{ int l,r; int num,lazy,lc,rc;}my[maxn<<2];void push_up(int o){ my[o].lc=my[o<<1].lc;my[o].rc=my[(o<<1)|1].rc; int ans=my[o<<1].num+my[(o<<1)|1].num; if(my[o<<1].rc==my[(o<<1)|1].lc)ans--; my[o].num=ans;}void push_down(int o){ if(my[o].lazy){ my[o<<1].lazy=my[(o<<1)|1].lazy=my[o].lazy; my[o<<1].num=my[(o<<1)|1].num=1; my[o<<1].lc=my[o<<1].rc=my[o].lc; my[(o<<1)|1].lc=my[(o<<1)|1].rc=my[o].lc; my[o<<1].lazy=0; }}void build(int o,int l,int r){ int mid=(l+r)/2; my[o].l=l;my[o].r=r;my[o].num=0;my[o].lazy=0; if(l==r){ my[o].num=1; my[o].lc=my[o].rc=col[pre[l]]; return; } build(o<<1,l,mid);build((o<<1)|1,mid+1,r); push_up(o);}void update(int o,int l,int r,int x){ if(my[o].l==l&&my[o].r==r){ my[o].num=my[o].lazy=1; my[o].lc=my[o].rc=x; return; } push_down(o); int mid=(my[o].l+my[o].r)/2; if(r<=mid)update(o<<1,l,r,x); else if(l>mid)update((o<<1)|1,l,r,x); else{ update(o<<1,l,mid,x);update((o<<1)|1,mid+1,r,x); } push_up(o);}void uptree(int u,int v,int c){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); update(1,id[top[u]],id[u],c); u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v); update(1,id[v],id[u],c);}int lc,rc;int query(int o,int l,int r,int L,int R){ if(my[o].l==L)lc=my[o].lc; if(my[o].r==R)rc=my[o].rc; if(my[o].l==l&&my[o].r==r)return my[o].num; push_down(o); int mid=(my[o].l+my[o].r)/2; if(r<=mid)return query(o<<1,l,r,L,R); else if(l>mid)return query((o<<1)|1,l,r,L,R); else{ int ans=query(o<<1,l,mid,L,R); ans+=query((o<<1)|1,mid+1,r,L,R); if(my[o<<1].rc==my[(o<<1)|1].lc)ans--; return ans; } push_up(o);}int qutree(int u,int v){ int ans1=-1,ans2=-1,ans=0; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v),swap(ans1,ans2); ans+=query(1,id[top[u]],id[u],id[top[u]],id[u]); if(rc==ans1)ans--; ans1=lc;u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v),swap(ans1,ans2); ans+=query(1,id[v],id[u],id[v],id[u]); if(rc==ans1)ans--; if(lc==ans2)ans--; return ans;}int main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int m; cin>>n>>m; for(int i=1;i<=n;i++)cin>>col[i]; for(int i=1;i<n;i++){ int u,v;cin>>u>>v; G[u].push_back(v);G[v].push_back(u); } dfs1(1,1,1);dfs2(1,1);build(1,1,n); while(m--){ char s[150]; cin>>s; int x,y; if(s[0]=='C'){ int c;cin>>x>>y>>c; uptree(x,y,c); } else{ cin>>x>>y; cout<<qutree(x,y)<<endl; } } return 0;} P2146 [NOI2015]软件包管理器123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll mod=998244353;const int maxn=1e6+50;const ll inf=0x3f3f3f3f3f3f3f3fLL;int n,q,col[maxn];vector<int>G[maxn];int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];int id[maxn],pre[maxn],cnt=0;void dfs1(int u,int f,int deep){ size[u]=1; fa[u]=f;son[u]=0;dep[u]=deep; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==f)continue; dfs1(v,u,deep+1); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; }}void dfs2(int u,int root){ id[u]=++cnt;top[u]=root;pre[cnt]=u; if(son[u])dfs2(son[u],root); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); }}int sum[maxn<<2],lazy[maxn<<2];void push_up(int o){ sum[o]=sum[o<<1]+sum[o<<1|1];}void push_down(int o,int l,int r){ if(lazy[o]){ int mid=(l+r)/2; if(lazy[o]==-1)sum[o<<1]=sum[o<<1|1]=0,lazy[o<<1]=lazy[o<<1|1]=-1; else sum[o<<1]=mid-l+1,sum[o<<1|1]=r-mid,lazy[o<<1]=lazy[o<<1|1]=1; lazy[o]=0; }}void uninstall(int o,int l,int r,int ql,int qr,int x){ if(ql<=l&&r<=qr){ if(!x)lazy[o]=-1,sum[o]=0; else lazy[o]=1,sum[o]=r-l+1;return; } int mid=(l+r)/2;push_down(o,l,r); if(mid>=ql)uninstall(o<<1,l,mid,ql,qr,x); if(mid<qr)uninstall(o<<1|1,mid+1,r,ql,qr,x); push_up(o);}void install(int v,int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); uninstall(1,1,n,id[top[x]],id[x],v); x=fa[top[x]]; } if(dep[x]<dep[y])swap(x,y); uninstall(1,1,n,id[y],id[x],v);}int main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); cin>>n; for(int i=2;i<=n;i++){ int u; cin>>u;u++; G[i].push_back(u); G[u].push_back(i); } dfs1(1,1,1); dfs2(1,1); int m;cin>>m; char op[150]; while(m--){ int x; cin>>op>>x;x++;int p=sum[1]; if(op[0]=='i'){ install(1,x,1); cout<<abs(p-sum[1])<<endl; } else{ uninstall(1,1,n,id[x],id[x]+size[x]-1,0); cout<<abs(p-sum[1])<<endl; } } return 0;}/*70 0 0 1 1 55install 5install 6uninstall 1install 4uninstall 0*/ P3258 [JLOI2014]松鼠的新家 (区间加减)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll mod=998244353;const int maxn=3e5+50;const ll inf=0x3f3f3f3f3f3f3f3fLL;vector<int>G[maxn];int id[maxn],dep[maxn],pre[maxn],fa[maxn],size[maxn],son[maxn],cnt,top[maxn];void dfs1(int now,int f,int deep){ fa[now]=f;size[now]=1;son[now]=0;dep[now]=deep; for(auto i:G[now]){ if(i==f)continue; dfs1(i,now,deep+1); size[now]+=size[i]; if(size[i]>size[son[now]])son[now]=i; }}void dfs2(int now,int root){ id[now]=++cnt;pre[cnt]=now;top[now]=root; if(son[now])dfs2(son[now],root); for(auto i:G[now]){ if(i==fa[now]||i==son[now])continue; dfs2(i,i); }}int sum[maxn<<2],lazy[maxn<<2];void push_up(int o){ sum[o]=sum[o<<1]+sum[o<<1|1];}void push_down(int o,int l,int r){ if(lazy[o]){ int mid=(l+r)/2; lazy[o<<1]+=lazy[o]; lazy[o<<1|1]+=lazy[o]; sum[o<<1]+=(mid-l+1)*lazy[o]; sum[o<<1|1]+=(r-mid)*lazy[o]; lazy[o]=0; }}void update(int o,int l,int r,int ql,int qr,int w){ int mid=(l+r)/2; if(ql<=l&&r<=qr){ lazy[o]+=w; sum[o]+=(r-l+1)*w; return; } push_down(o,l,r); if(ql<=mid)update(o<<1,l,mid,ql,qr,w); if(qr>mid)update(o<<1|1,mid+1,r,ql,qr,w); push_up(o);}void print(int o,int l,int r,int ql,int qr){ cout<<"o=="<<o<<" l="<<l<<" r="<<r<<" ql="<<ql<<" qr="<<qr<<endl; cout<<"sum="<<sum[o]<<endl;}int query(int o,int l,int r,int ql,int qr){ //print(o,l,r,ql,qr); if(l==r){ return sum[o]; } int mid=(l+r)/2; push_down(o,l,r); if(ql<=mid)return query(o<<1,l,mid,ql,qr); else return query(o<<1|1,mid+1,r,ql,qr);}void uptree(int u,int v,int w){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); update(1,1,cnt,id[top[u]],id[u],w); u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v); update(1,1,cnt,id[v],id[u],w);}int a[maxn];// 适用于正负整数template <class T>inline bool read(T &ret){ char c; int sgn; if (c = getchar(), c == EOF) return 0; //EOF while (c != '-' && (c < '0' || c > '9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1;}inline void out(int x){ if (x > 9) out(x / 10); putchar(x % 10 + '0');}int main(){ /* std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);*/ int n; //cin>>n; read(n); for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<n;i++){ int u,v; // cin>>u>>v; read(u);read(v); G[u].push_back(v); G[v].push_back(u); } dfs1(1,1,1);dfs2(1,1); for(int i=1;i<n;i++){ uptree(a[i],a[i+1],1); uptree(a[i+1],a[i+1],-1); } for(int i=1;i<=n;i++){ // cout<<query(1,1,n,id[i],id[i])<<endl; out(query(1,1,n,id[i],id[i])); puts(""); } return 0;}